class WebSocket {
  /**
     * 初始化时传入参数
     * @param {
     *  wsUrl 必传参数，ws链接路径
     *  wsPort 必传参数，ws端口
     *  callback 必传参数，ws消息回调函数
     *  data 选传参数，ws初始化时send参数
     * } params
     */
  constructor (params) {
    this.params = params
    this.initSocket(params)
  }

  /**
     * websocket初始化调用函数
     * @param {Object} params 初始化传入参数，选填wsUrl
     */
  initSocket (params) {
    // const wsHostName = '192.168.7.49:';
    // params.wsPort = '9000';
    const wsHostName = location.hostname + ':'
    this.wsUrl = `ws://${wsHostName}${params.wsPort}${params.wsUrl}`
    this.lockReconnect = false
    this.closeFlag = false
    this.websock = new WebSocket(this.wsUrl)
    this.websock.onopen = this.websocketopen.bind(this)
    this.websock.onmessage = this.websocketonmessage.bind(this)
    this.websock.onclose = this.websocketclose.bind(this)
    this.websock.onerror = this.websocketerror.bind(this)
    // 心跳检测
    this.heartCheck = {
      timeout: 10000, // 10秒
      timeoutObj: null,
      serverTimeoutObj: null,
      reset: function () {
        clearTimeout(this.timeoutObj)
        clearTimeout(this.serverTimeoutObj)
        return this
      },
      start: function (thisApp) {
        const _this = this
        const _thisApp = thisApp
        this.timeoutObj = setTimeout(() => {
          // 这里发送一个心跳，后端收到后，返回一个心跳消息，
          // onmessage拿到返回的心跳就说明连接正常
          _thisApp.socketSend({'Action': 'HEARTBEAT'})
          _this.serverTimeoutObj = setTimeout(() => { // 如果超过一定时间还没重置，说明后端主动断开了
            _thisApp.socketClose() // 如果onclose会执行reconnect，我们执行socketClose就行了.如果直接执行reconnect 会触发onclose导致重连两次
          }, _this.timeout)
        }, this.timeout)
      }
    }
  }

  // websocket open回调函数
  websocketopen () {
    this.params.data && this.socketSend(this.params.data)
    console.log('WebSocket建立连接')
    this.heartCheck.reset().start(this)
  }
  // websocket onmessage回调函数
  websocketonmessage (res) {
    this.heartCheck.reset().start(this)
    console.log(res.data)
    const data = JSON.parse(res.data)
    if (data.Action && data.Action !== 'HEARTBEAT') {
      this.params.callback(data)
    }
  }
  // websocket close回调函数
  websocketclose (e) {
    console.log('WebSocket断开连接' + e.code)
  }
  // websocket error回调函数
  websocketerror (e) {
    console.log('WebSocket连接发生错误' + e.type)
    if (!this.closeFlag) {
      this.reconnect()
    }
  }

  // 关闭链接
  socketClose () {
    this.closeFlag = true
    this.socketSend({'Action': 'DISCONNECT'})
    this.heartCheck.reset()
    this.reconnectTimeOut && clearTimeout(this.reconnectTimeOut)
    this.websock.close()
  }

  // 异常重连
  reconnect () {
    if (this.lockReconnect) return
    this.lockReconnect = true
    // 没连接上会一直重连，设置延迟避免请求过多
    this.reconnectTimeOut = setTimeout(() => {
      this.initSocket(this.params)
      this.lockReconnect = false
    }, 2000)
  }

  // 发送数据
  socketSend (data) {
    const _this = this
    if (this.websock.readyState === this.websock.OPEN) {
      console.log(data)
      // 若是ws开启状态
      if (Object.prototype.toString.call(data) === '[object Array]') {
        data.map((item, index) => {
          this.websock.send(JSON.stringify(item))
        })
      } else if (Object.prototype.toString.call(data) === '[object String]') {
        this.websock.send(JSON.stringify(data))
      } else if (Object.prototype.toString.call(data) === '[object Object]') {
        this.websock.send(JSON.stringify(data))
      } else {
        console.error('send数据类型错误，需要array或string')
      }
    } else if (this.websock.readyState === this.websock.CONNECTING) {
      console.log('WebSocket正在开启中')
      // 若是 正在开启状态，则等待1s后重新调用
      setTimeout(function () {
        _this.socketSend(data)
      }, 1000)
    } else {
      console.log('WebSocket连接未开启，请先建立链接')
    }
  }
}
export default WebSocket
